#ifndef EMS_PROTOCOL_MODBUS_MODBUS_RTU_H
#define EMS_PROTOCOL_MODBUS_MODBUS_RTU_H

#include "protocol/ProtocolInterface.h"
#include <string>
#include <memory>

typedef struct _modbus modbus_t;

namespace ems {
namespace protocol {

class ModbusRTU : public ProtocolInterface {
public:
    ModbusRTU(const std::string& device, int baudRate, char parity, int dataBits, int stopBits);
    virtual ~ModbusRTU();
    
    bool connect() override;
    void disconnect() override;
    bool isConnected() const override;
    
    void setSlaveId(int slaveId);
    void setTimeout(int timeoutMs);
    
    bool readHoldingRegisters(uint16_t address, uint16_t count, std::vector<uint16_t>& data) override;
    bool readInputRegisters(uint16_t address, uint16_t count, std::vector<uint16_t>& data) override;
    bool readCoils(uint16_t address, uint16_t count, std::vector<bool>& data) override;
    bool readDiscreteInputs(uint16_t address, uint16_t count, std::vector<bool>& data) override;
    
    bool writeSingleRegister(uint16_t address, uint16_t value) override;
    bool writeMultipleRegisters(uint16_t address, const std::vector<uint16_t>& values) override;
    bool writeSingleCoil(uint16_t address, bool value) override;
    bool writeMultipleCoils(uint16_t address, const std::vector<bool>& values) override;
    
    std::string getLastError() const override;
    ProtocolType getType() const override { return ProtocolType::MODBUS_RTU; }

private:
    std::string device_;
    int baudRate_;
    char parity_;
    int dataBits_;
    int stopBits_;
    int slaveId_;
    int timeout_;
    
    modbus_t* ctx_;
    bool connected_;
    mutable std::string lastError_;
    
    void updateLastError() const;
};

}  // namespace protocol
}  // namespace ems

#endif  // EMS_PROTOCOL_MODBUS_MODBUS_RTU_H